package com.szeldon.pj.jps.exp;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.szeldon.pj.jps.data.store.SBAStore;
import com.szeldon.pj.jps.datastore.SimpleObject;
import com.szeldon.pj.jps.envs.ENVS;
import com.szeldon.pj.jps.envs.ENVSBinder;
import com.szeldon.pj.jps.envs.ENVSStackFrame;
import com.szeldon.pj.jps.qres.AbstractQueryResult;
import com.szeldon.pj.jps.qres.BagResult;
import com.szeldon.pj.jps.qres.BinderResult;
import com.szeldon.pj.jps.qres.BooleanResult;
import com.szeldon.pj.jps.qres.IntegerResult;
import com.szeldon.pj.jps.qres.QResStack;
import com.szeldon.pj.jps.qres.RealResult;
import com.szeldon.pj.jps.qres.StringResult;
import com.szeldon.pj.jps.visitor.ASTVisitor;

public class AsBinaryExpression extends BinaryExpression {

	/**
	 * 
	 * @param leftExpression
	 * @param rightExpression
	 */
	public AsBinaryExpression(Expression leftExpression, Expression rightExpression) {
		super(leftExpression, rightExpression);
	}

	/**
	 * 
	 * @param astVisitor
	 * @param envs
	 * @param qResStack
	 * @param store
	 */
	public void accept(ASTVisitor astVisitor, ENVS envs, QResStack qResStack, SBAStore store) {
		if (!(rightExpression instanceof NameExpression)) {
			throw new IllegalStateException("Right expression for As expression must be of "
					+ "name expression type (it is" + rightExpression.getClass().getName() + ").");
		}

		String name = ((NameExpression) rightExpression).getName();
		BagResult expressionResult = new BagResult();

		astVisitor.accept(leftExpression);

		AbstractQueryResult qResStackPoppedResult = qResStack.pop();
		BagResult leftResultsBag = null;

		if (qResStackPoppedResult instanceof BagResult) {
			leftResultsBag = (BagResult) qResStackPoppedResult;
		} else if (qResStackPoppedResult instanceof BooleanResult || qResStackPoppedResult instanceof IntegerResult
				|| qResStackPoppedResult instanceof RealResult || qResStackPoppedResult instanceof StringResult) {
			Set<AbstractQueryResult> leftResultsSet = new HashSet<AbstractQueryResult>();
			leftResultsSet.add(qResStackPoppedResult);
			leftResultsBag = new BagResult(leftResultsSet);
		} else {
			throw new IllegalStateException("Currently As expression doesn't support "
					+ qResStackPoppedResult.getClass().getName() + " as result of left expression.");
		}

		for (AbstractQueryResult currentLeftResult : leftResultsBag.getElements()) {
			expressionResult.addResult(new BinderResult(name, currentLeftResult));
		}

		List<ENVSBinder> bindersList = envs.nested(expressionResult, store);
		envs.push(new ENVSStackFrame(bindersList));

		qResStack.push(expressionResult);
	}

	@Override
	public int compareTo(SimpleObject object) throws IllegalStateException {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public String getValueAsString() {
		return "as";
	}

}
